package com.gzc.just.play.client.war3server;

import com.gzc.just.play.Const;
import com.gzc.just.play.Utils;
import com.gzc.just.play.client.Client;
import com.gzc.just.play.proto.War3Proto;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.TimeUnit;

class War3TcpListener implements Runnable {
    private static final Logger logger = LogManager.getLogger(War3TcpListener.class);
    private final String otherWar3Ip;

    public War3TcpListener(String otherWar3Ip) {
        this.otherWar3Ip = otherWar3Ip;
    }

    @Override
    public void run() {
        try (var otherWar3ServerChannel = AsynchronousServerSocketChannel.open()) {
            logger.info("otherWar3Server tcp listen start,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
            // 监听其他远程客户端代理的war3Ip的tcp服务器
            otherWar3ServerChannel.bind(new InetSocketAddress(otherWar3Ip, Const.WAR3_PORT));
            logger.info("otherWar3Server tcp listen ok,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);

            while (!Thread.interrupted()) {
                try {
                    var connectOtherWar3ServerChannel = otherWar3ServerChannel.accept().get();
                    logger.info("tcp connect otherWar3Server from clientIp={},port={}",
                            connectOtherWar3ServerChannel.getRemoteAddress(), Const.WAR3_PORT);

                    // 每个新连接交给线程池异步处理
                    Client.executor.submit(() -> {
                        // 连接war3 proxyServer
                        try (var connectProxyServerChannel = AsynchronousSocketChannel.open()) {
                            logger.info("connect proxyServer start,proxyServerIp={},proxyServerPort={}",
                                    Client.SERVER_IP, Client.SERVER_PORT);
                            connectProxyServerChannel.connect(new InetSocketAddress(Client.SERVER_IP, Client.SERVER_PORT))
                                    .get(Const.TIMEOUT_SECOND, TimeUnit.SECONDS);
                            logger.info("connect proxyServer ok,proxyServerIp={},proxyServerPort={}",
                                    Client.SERVER_IP, Client.SERVER_PORT);

                            // 发送WAR3_CONNECT消息
                            War3Proto.War3Message war3ConnectMessage = War3Proto.War3Message.newBuilder()
                                    .setType(War3Proto.MessageType.WAR3_CONNECT)
                                    .setTargetIp(otherWar3Ip)
                                    .build();
                            Utils.sendProtobufMessage(connectProxyServerChannel, war3ConnectMessage);

                            logger.info("war3server start transferData,otherWar3Ip={},port={},proxyServerIp={},proxyServerPort={}",
                                    otherWar3Ip, Const.WAR3_PORT, Client.SERVER_IP, Client.SERVER_PORT);
                            // 开始交换数据
                            var taskFuture1 = Client.executor.submit(() -> Utils.transferData(connectProxyServerChannel, connectOtherWar3ServerChannel));
                            var taskFuture2 = Client.executor.submit(() -> Utils.transferData(connectOtherWar3ServerChannel, connectProxyServerChannel));
                            taskFuture1.get();
                            taskFuture2.get();
                        } catch (InterruptedException e) {
                            // 正常中断，记录为调试信息
                            logger.debug("TCP data transfer interrupted due to thread interruption", e);
                            Thread.currentThread().interrupt(); // 恢复中断状态
                        } catch (Exception e) {
                            logger.error(e.getMessage(), e);
                        }
                    });
                } catch (InterruptedException e) {
                    // accept() 被中断，记录为调试信息
                    logger.debug("TCP accept() interrupted due to thread interruption", e);
                    Thread.currentThread().interrupt(); // 恢复中断状态
                    break; // 退出循环
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }
}
